/* Copyright (C) 2008 Sahid Ferdjaoui <sahid@funraill.org>
 *
 *   This file is part of Postmemd.
 *
 * Postmemd is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */



#include "pm_head.h"
#include "pm_log.h"
#include "pm_config.h"
#include "pm_poll.h"
#include "pm_slaves.h"

#include <ev.h>

#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>


/** general input/ouput */
io_poller io;

/** general Config Postmemd Server */
config conf;

/** slaves pool */
pool_slaves_t * pool;


int
main (int argc, const char * argv[])
{
	struct ev_loop * loop;
	int i;
	pfd_t m2s[2],
		    s2m[2];
	pid_t pid;


	/** memory lock */
#ifdef _POSIX_MEMLOCK
	if (conf.mem_lock == 1)
		{
			if (mlockall (MCL_CURRENT | MCL_FUTURE) == -1)
				pm_log_error ("Memory lock failed, check your permision. But server continue...", PM_PRINT_ERRNO);
		}
#else
	pm_log_error ("Your system dont have memory lock routine. But server continue...", PM_NOPRINT_ERRNO);
#endif

	/** initialize config */
	pm_init_config ();

	/** initialize events loop */
	loop = ev_default_loop (conf.loop_flag);

	/** new socket listener */
	if (pm_socket_create (& io.listener, conf.interface, conf.port, conf.backlog) == -1)
		{
			pm_log_error ("Error fatal, listening socket not defined", PM_NOPRINT_ERRNO);
			return -1;
		}

	/** initialize pool */
	pm_slaves_pool_init (& pool);

	/** load slaves */
	for (i = 0; i < conf.num_slaves; i ++)
		{
			pipe (m2s);
			pipe (s2m);

			pid = fork ();
			if (pid == 0)
				{
					fprintf (stdout, "slave read %d, write %d\n",m2s[0], s2m[1]);
					pm_slaves_init (m2s[0], s2m[1], loop);
					fprintf (stdout, "slave close %d, %d\n",m2s[1], s2m[0]);
					close (s2m[0]);
					close (m2s[1]);
				}
			else
				if (pid > 0)
					{
						fprintf (stdout, "master read %d, write %d\n",s2m[0], m2s[1]);
						pm_slaves_pool_add (& pool, pid, s2m[0], m2s[1], loop);
						fprintf (stdout, "master close %d, %d\n",s2m[1], m2s[0]);
						close (s2m[1]);
						close (m2s[0]);
					}
				else
					{
						pm_log_error ("fatal error - fork ()", PM_PRINT_ERRNO);
						return -1;
					}
		}

	pm_slaves_pool_view (pool);
	fprintf (stdout, "socket listener %d\n", io.listener);

	/** record listener in event loop */
	pm_record_fd (EV_A_ & io.event, io.listener, pm_event_handler, EV_READ); 
	
	/** wait new events */
	ev_loop (EV_A_ 0);

	return 0; /* finish success */
}
